package com.hqd.ch03.v14;


import com.hqd.ch03.v14.config.BeanDefinition;
import com.hqd.ch03.v14.listener.BeanFactoryListener;
import com.hqd.ch03.v14.listener.event.BeanFactoryEndEvent;
import com.hqd.ch03.v14.listener.event.BeanFactoryStartedEvent;
import com.hqd.ch03.v14.reader.support.XmlBeanDefinitionReader;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.ClassUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class SpringImitationV14Xml extends SpringImitationV14 {
    private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanDefinitionRegistry);

    public SpringImitationV14Xml(String location) {
        this.reader.loadBeanDefinition(resourceLoader.getResource(location));
        registerListeners();
        publishEvent(new BeanFactoryStartedEvent(this));
        //doSomething
        publishEvent(new BeanFactoryEndEvent(this));
    }

    protected void registerListeners() {
        List<String> listenerBeanNames = getBeanNamesForType(BeanFactoryListener.class);
        if (CollectionUtils.isNotEmpty(listenerBeanNames)) {
            for (String listenerBeanName : listenerBeanNames) {
                addBeanFactoryListener(getBean(listenerBeanName, BeanFactoryListener.class));
            }
        }
    }

    protected List<String> getBeanNamesForType(Class<?> beanClass) {
        String[] beanDefinitionNames = beanDefinitionRegistry.getBeanDefinitionNames();
        List<String> listenerNames = new ArrayList<>(beanDefinitionNames.length);
        Arrays.stream(beanDefinitionNames).forEach(beanName -> {
            BeanDefinition beanDefinition = beanDefinitionRegistry.getBeanDefinition(beanName);
            try {
                if (ClassUtils.isAssignable(ClassUtils.getClass(beanDefinition.getBeanClass()), beanClass)) {
                    listenerNames.add(beanName);
                }
            } catch (ClassNotFoundException e) {
                throw new RuntimeException(e);
            }
        });
        return listenerNames;

    }
}
